/*
 * Copyright (c) 2023 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#ifndef DEV_NCSI_OVER_MCTP_HUAWEI_H
#define DEV_NCSI_OVER_MCTP_HUAWEI_H

#include <mctp/mctp.h>
#include <ncsi/ncsi_huawei.h>
#include <ncsi_over_mctp/ncsi_over_mctp.h>
#include <ncsi_over_mctp/ncsi_over_mctp_standard.h>

const uint8_t HUAWEI_OEM_COMMAND_REV_ID = 0x00;

namespace dev {

// #define HUAWEI_MANUFACTURE_ID 0x000007DB
#define COMMON_DATA(cmd_id, sub_cmd_id, extra_cmd)                                                 \
    {0x00, 0x00, 0x07, 0xDB, HUAWEI_OEM_COMMAND_REV_ID, cmd_id, sub_cmd_id, extra_cmd}
#define COMMON_DATA_SIZE 7

using error_code_map_t      = std::map<uint16_t, std::string>;
using response_error_code_t = std::map<uint8_t, error_code_map_t>;

typedef struct ncsi_bdf_info {
    uint8_t bus;
    uint8_t device;
    uint8_t function;
} ncsi_bdf_info_t;

typedef struct ncsi_link_ability {
    std::string link_width;
    std::string link_speed;
} ncsi_link_ability_t;

typedef struct ncsi_link_info {
    std::string link_width;
    std::string link_speed;
} ncsi_link_info_t;

#define MCTP_NCSI_DCBX_FIELD_LEN 8
typedef struct ncsi_dcbx_status {
    uint8_t cos2_up[MCTP_NCSI_DCBX_FIELD_LEN];
    uint8_t up_pgid[MCTP_NCSI_DCBX_FIELD_LEN];
    uint8_t pgpct[MCTP_NCSI_DCBX_FIELD_LEN];
    uint8_t strict[MCTP_NCSI_DCBX_FIELD_LEN];
    uint8_t pfcmap;

} ncsi_dcbx_status_t;

typedef struct ncsi_fault_state_code {
    uint8_t  health_state;
    uint8_t  error_count;
    uint16_t error_code[NCSI_HUAWEI_FAULT_STATE_CODE_COUNT];
} ncsi_fault_state_code_t;

typedef struct ncsi_optical_module_info {
    uint8_t     part_number[MCTP_NCSI_OPTICAL_MODULE_FIELD_LEN];
    uint8_t     manufacturer[MCTP_NCSI_OPTICAL_MODULE_FIELD_LEN];
    uint8_t     serial_number[MCTP_NCSI_OPTICAL_MODULE_FIELD_LEN];
    std::string medium_type;
    std::string connector_type;
    uint16_t    transceiver_distance;
    bool        rx_loss_status;
    bool        tx_fault_status;
    double      tx_bias_current_milliamps;
    double      tx_power_milliwatts;
    double      rx_power_milliwatts;
    double      supply_voltage;
    double      tx_power_upper_threshold_critical;
    double      rx_power_upper_threshold_critical;
    std::string wave_length_nanometer;
    std::string identifier;
    uint16_t    temperature_lower_threshold_critical;
    uint16_t    temperature_upper_threshold_critical;
} ncsi_optical_module_info_t;

// 日志类型配置结构
typedef struct ncsi_log_type_config {
    uint32_t log_type;        // 日志类型编号 (对应extra_cmd)
    uint32_t total_frame;     // 需要读取的帧数
    uint32_t base_offset;     // 起始偏移地址
    std::string name_prefix;  // 文件名前缀
} ncsi_log_type_config_t;

class MC_API ncsi_over_mctp_huawei : public ncsi_over_mctp_standard {
public:
    ncsi_over_mctp_huawei(mctp& mctp_obj) : ncsi_over_mctp_standard(mctp_obj) {};
    bool get_bdf(uint8_t package_id, uint8_t channel_id, ncsi_bdf_info_t* bdf_info);
    bool get_chip_temp(uint8_t package_id, uint8_t channel_id, uint16_t* chip_temp);
    bool get_om_temp(uint8_t package_id, uint8_t channel_id, uint16_t* om_temp);
    bool get_dcbx_status(uint8_t package_id, uint8_t channel_id, ncsi_dcbx_status_t* dcbx_status);
    bool get_link_ability(uint8_t package_id, uint8_t channel_id,
                          ncsi_link_ability_t* link_ability);
    bool get_link_info(uint8_t package_id, uint8_t channel_id, ncsi_link_info_t* link_info);
    bool get_mac_addr(uint8_t package_id, uint8_t channel_id, uint8_t* mac_addr, uint8_t len);
    bool get_default_mac_addr(uint8_t package_id, uint8_t channel_id, uint8_t* mac_addr,
                              uint8_t len);
    bool get_fault_state_code(uint8_t package_id, uint8_t channel_id,
                              ncsi_fault_state_code_t* fault_state_code);
    bool enable_lldp_capability(uint8_t package_id, uint8_t channel_id);
    bool disable_lldp_capability(uint8_t package_id, uint8_t channel_id);
    bool get_lldp_capability(uint8_t package_id, uint8_t channel_id, uint8_t* lldp_capability);
    bool enable_lldp_tx(uint8_t package_id, uint8_t channel_id);
    bool enable_lldp_tx_old(uint8_t package_id, uint8_t channel_id);
    bool disable_lldp_tx(uint8_t package_id, uint8_t channel_id);
    bool disable_lldp_tx_old(uint8_t package_id, uint8_t channel_id);
    bool get_lldp_tx_enable(uint8_t package_id, uint8_t channel_id, uint8_t* lldp_tx_enable);
    bool get_optical_module_info(uint8_t package_id, uint8_t channel_id,
                                 ncsi_optical_module_info_t* optical_module_info);
    bool collect_logs_by_ncsi(uint8_t package_id, std::vector<std::string>& log_files, 
                             const std::string& log_dir);

private:
    bool get_log_by_ncsi_internal(uint8_t package_id, uint32_t log_type, 
                                  uint32_t total_frame, uint32_t base_offset, 
                                  std::string& log_data);
    bool send_get_log_command(uint8_t package_id, uint8_t sub_cmd_id, uint32_t log_type, 
                             const oem_huawei_get_log_req_t& request, std::string& response);
};

} // namespace dev

#endif // DEV_NCSI_OVER_MCTP_HUAWEI_H
